﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Threading;
using log4net;
using log4net.Config;
using WikiBotDll;
using Timer = System.Timers.Timer;

[assembly: XmlConfigurator(ConfigFileExtension = "log4net", Watch = true)]
namespace WikiBrodskyWcf
{    
    class Program
    {
        private static readonly ColorLogger log = new ColorLogger(LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType));
        
        public static ColorLogger Log
        {
            get { return log; }
        }

        public static WikiBot MyBot
        {
            get { return myBot; }
            private set { myBot = value; }
        }

        private static Timer timer;

        private static int timerPeriod;

        public static bool DictionaryWorker { get; set; }

        public static bool AllPagesFromDictionarysWorker { get; set; }

        /// <summary>Викибот
        /// </summary>
        private static WikiBot myBot = new WikiBot();

        public static bool Working { get; set; }

        private static bool isWorkerBusy;

        public static int TimerPeriod
        {
            get { return timerPeriod; }
            set
            {
                if (value < 1)
                {
                    value = 1;
                }
                timerPeriod = value;
                if (timer == null)
                {                    
                    timer = new Timer(TimerPeriod * 60000);
                    timer.Elapsed += timer_Elapsed;
                }
                else
                {
                    timer.Interval = value * 60000;
                }                
                timer.Enabled = true;

            }
        }

        public static bool BotConnected
        {
            get { return MyBot.Connected; }
        }

        static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            var tmpDate = DateTime.Now;
            try
            {
                log.Info("Start worker with period " + TimerPeriod + " minutes");
                isWorkerBusy = true;
                timer.Enabled = !isWorkerBusy;

                if (DictionaryWorker)
                {
                    log.Info("start DictionaryWorker");
                    MyBot.LoadListOfAllPages();
                    log.Info("Загрузка словаря...");
                    MyBot.Dictionary.Load(MyBot.Pages);
                    log.Info("Обновление словарей...");
                    MyBot.Dictionary.ProcessAllPagesToDictionay(MyBot.Pages);
                    log.Info("end DictionaryWorker");
                }
                else
                {
                    log.Info("DictionaryWorker disabled - skipped");
                }

                if (AllPagesFromDictionarysWorker)
                {
                    if (!DictionaryWorker || MyBot.Pages.Count() <= 0)
                    {
                        MyBot.LoadListOfAllPages();
                        MyBot.Dictionary.Load(MyBot.Pages);
                    }
                    log.Info("start AllPagesFromDictionarysWorker");
                    MyBot.Dictionary.ProcessAllPagesFromDictionary(MyBot.Pages);
                    log.Info("end AllPagesFromDictionarysWorker");
                }
                else
                {
                    log.Info("AllPagesFromDictionarysWorker disabled - skipped");
                }
            }
            catch (Exception ex)
            {
                log.Error("timer_Elapsed error: " + ex);
            }
            finally
            {
                isWorkerBusy = false;
                timer.Enabled = !isWorkerBusy;
                log.Info("End worker with period " + TimerPeriod + " started at " + tmpDate + ". Time elapsed: " + (DateTime.Now-tmpDate));
            }

        }

        private static void Main(string[] args)
        {
            try
            {
                log.Info("Starting application");

                log.Info("creating WikiBrodscyWcfService...");
                var myService = new ServiceHost(typeof (WikiBrodscyWcfService));

                var serviceDesciption = myService.Description;

                log.Info("use " + serviceDesciption.Endpoints.Count + " endpoints:");
                foreach (var endpoint in serviceDesciption.Endpoints)
                {
                    Log.InfoFormat("Endpoint - address:  {0}", endpoint.Address);
                    Log.InfoFormat("         - binding name:\t\t{0}", endpoint.Binding.Name);
                    Log.InfoFormat("         - contract name:\t\t{0}", endpoint.Contract.Name);
                }

                log.Info("Opening service...");
                myService.Open();
                                
                log.Info("Connecting...");

                MyBot.Connect("Wikibrodsky.ru/wiki", "WikiBOT", "wikibot123");
                
                log.Info("Enable timer with period 1");
                TimerPeriod = 1;

                log.Info("Waiting commands...");
                Working = true;

                log.Info("Enable DictionaryWorker");
                DictionaryWorker = true;

                log.Info("Enable AllPagesFromDictionarysWorker");
                AllPagesFromDictionarysWorker = true;

                log.GreenInfo("Working. Press Enter to stop");
                Console.ReadLine();                

                log.Info("Stoping application");
                if (myService.State != CommunicationState.Closed)
                    myService.Close();
            }
            catch (AddressAlreadyInUseException ex)
            {
                log.Error("Error starting service - another service is startet already. \nException: " + ex);
            }
            catch (Exception ex)
            {
                log.Error("Error service: " + ex.Message, ex);
            }
        }

    }
}
